package com.th.therp.service.Impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.th.therp.context.BaseContext;
import com.th.therp.exception.BaseException;
import com.th.therp.mapper.SaleMapper;
import com.th.therp.pojo.dto.SaleDto;
import com.th.therp.pojo.dto.page.SalePageQueryDTO;
import com.th.therp.pojo.emtity.Inventory;
import com.th.therp.pojo.emtity.Material;
import com.th.therp.pojo.emtity.Sale;
import com.th.therp.pojo.result.PageResult;
import com.th.therp.pojo.vo.DashboardMonthVo;
import com.th.therp.pojo.vo.SaleVo;
import com.th.therp.service.*;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Log4j2
@Service
public class SaleServiceImpl implements SaleService {

    @Autowired
    private SaleMapper saleMapper;

    @Autowired
    private UserService userService;

    @Autowired
    private StoreService storeService;

    @Autowired
    private CustomerService customerService;

    @Autowired
    private MaterialService materialService;

    @Autowired
    private InventoryService inventoryService;

    @Autowired
    private MaterialBrandService materialBrandService;

    @Autowired
    private MaterialCategoryService materialCategoryService;

    @Override
    public void add(SaleDto saleDto) {
        String datePrefix = new SimpleDateFormat("yyyyMMdd").format(new Date());
        String barcode = "SO" + datePrefix + UUID.randomUUID().toString().substring(0, 6).toUpperCase();
        // 获取线程局部变量的userId用于查找用户名
        Long userId = BaseContext.getCurrentId();
        String operator = userService.findNameById(userId);
        // 查找商品单价
//        double purchasePrice = materialService.findPurchasePriceById(saleDto.getMaterial());
        double sellingPrice = materialService.findSellingPriceById(saleDto.getMaterial());
        double totalAmount = sellingPrice * saleDto.getQuantity();
        Sale sale = new Sale();
        BeanUtils.copyProperties(saleDto,sale);
        // 计算销售总金额
        sale.setTotalAmount(totalAmount);
        sale.setBarcode(barcode);
        sale.setCreateTime(LocalDateTime.now());
        sale.setOperator(operator);
        saleMapper.add(sale);
        // 向库存表新增商品库存数据(待完成)
        Integer categoryId = materialService.findMaterCategoryById(sale.getMaterial());
        Integer brandId = materialService.findMaterialBrandById(sale.getMaterial());
        String storeName = storeService.findNameById(sale.getStore());
        String materialName = materialService.findMaterialNameById(sale.getMaterial());
        String materialBarcode = materialService.findMaterialBarcodeById(sale.getMaterial());
        String materialCategory = materialCategoryService.findCategoryNameById(categoryId);
        String materialBrand = materialBrandService.findBrandNameById(brandId);
        Inventory inventory = Inventory.builder()
                .storeId(sale.getStore())
                .materialName(materialName)
                .materialBarcode(materialBarcode)
                .materialCategory(materialCategory)
                .materialBrand(materialBrand)
                .storeName(storeName)
                .quantity(sale.getQuantity())
                .build();
        log.info("仓库添加数据:{}",inventory);
        // 查询指定仓库商品是否存在，不存在则添加
        Integer quantity = inventoryService.findQuantityByStoreIdAndBarcode(inventory.getStoreId(),materialBarcode);
        if (quantity - sale.getQuantity() < 0){
            throw new BaseException("库存不足");
        }else if(quantity - sale.getQuantity() == 0){
            inventoryService.deleteByStoreIdAndBarcode(inventory);
        }else{
            // 如商品存在，则累加后修改
            inventory.setQuantity(quantity-sale.getQuantity());
            inventoryService.updateQuantityByStoreIdAndBarcode(inventory);
        }
    }

    @Override
    public PageResult page(SalePageQueryDTO salePageQueryDTO) {
        PageHelper.startPage(salePageQueryDTO.getPageNum(), salePageQueryDTO.getPageSize());
        Page<Sale> page = saleMapper.page(salePageQueryDTO);
        List<Sale> saleList = page.getResult();
        List<SaleVo> saleVoList = new ArrayList<>();
        saleList.forEach(sale -> {
            Integer storeId = sale.getStore();
            Integer customerId = sale.getCustomer();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日HH:mm:ss");
            String storeName = storeService.findNameById(storeId);
            String customerName = customerService.findNameById(customerId);
            String materialName = materialService.findMaterialNameById(sale.getMaterial());
            String materialBarcode = materialService.findMaterialBarcodeById(sale.getMaterial());
            String createTime = sale.getCreateTime().format(formatter);
            SaleVo saleVo = SaleVo.builder()
                    .id(sale.getId())
                    .barcode(sale.getBarcode())
                    .store(storeName)
                    .customer(customerName)
                    .materialName(materialName)
                    .materialBarcode(materialBarcode)
                    .totalAmount(sale.getTotalAmount())
                    .quantity(sale.getQuantity())
                    .operator(sale.getOperator())
                    .createTime(createTime)
                    .build();
            saleVoList.add(saleVo);
        });
        return new PageResult(page.getTotal(),saleVoList);
    }

    @Override
    public DashboardMonthVo findDashboardMonthVoByTime(String startOfDay, String endOfDay) {
        return saleMapper.findDashboardMonthVoByTime(startOfDay,endOfDay);
    }

    // 根据时间范围查找销售订单的数量
    @Override
    public Integer findQuantityByTime(String startTime, String endTime) {
        Integer quantity = saleMapper.findQuantityByTime(startTime,endTime);
        if (quantity != null){
            return quantity;
        }else {
            return 0;
        }
    }

    // 根据时间范围查找销售订单的金额
    @Override
    public Double findTotalAmountByTime(String startTime, String endTime) {
        Double totalAmount = saleMapper.findTotalAmountByTime(startTime,endTime);
        if (totalAmount != null){
            return totalAmount;
        }else {
            return 0.0;
        }
    }

    // 销售单退货
    @Override
    public void delete(Integer id) {
        //查找销售单商品编码
        Sale sale = saleMapper.findById(id);
        String materialBarcode = materialService.findMaterialBarcodeById(sale.getMaterial());
        //查询存放仓库的商品数量 构造仓库对象的信息
        Integer quantity = inventoryService.findQuantityByStoreIdAndBarcode(sale.getStore(),materialBarcode);
        Material material = materialService.findById(sale.getMaterial());
        Integer materialId = material.getId();
        Integer categoryId = material.getCategory();
        Integer brandId = material.getBrand();
        Integer storeId = sale.getStore();
        String storeName = storeService.findNameById(storeId);
        String materialName = materialService.findMaterialNameById(materialId);
        String materialCategoryName = materialCategoryService.findCategoryNameById(categoryId);
        String materialBrandName = materialBrandService.findBrandNameById(brandId);
        //如果仓库没有库存，则新增库存
        if (quantity==null){
            //查询构造库存单所需要的参数
            Integer updateQuantity = sale.getQuantity();
            Inventory inventory = Inventory.builder()
                    .storeId(storeId)
                    .storeName(storeName)
                    .materialName(materialName)
                    .materialBarcode(materialBarcode)
                    .materialCategory(materialCategoryName)
                    .materialBrand(materialBrandName)
                    .quantity(updateQuantity)
                    .build();
            saleMapper.delete(id);
            inventoryService.add(inventory);
        }else{
            //如果仓库有库存，则更新库存
            Integer updateQuantity = sale.getQuantity()+quantity;
            Inventory inventory = new Inventory();
            inventory.setStoreId(sale.getStore());
            inventory.setMaterialBarcode(materialBarcode);
            inventory.setQuantity(updateQuantity);
            saleMapper.delete(id);
            inventoryService.updateQuantityByStoreIdAndBarcode(inventory);
        }

    }
}
